package image;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.FileUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.util.HashMap;

/**
 * TODO
 *
 * @author shem
 * @since 2020/7/14
 */
public class BinTests {

    //blog.csdn.net/giantpoplar/java/article/details/47657333  大端序
    // int转换为byte[4]数组
    public static byte[] getByteArray(int i) {
        byte[] b = new byte[4];
        b[0] = (byte) ((i & 0xff000000) >> 24);
        b[1] = (byte) ((i & 0x00ff0000) >> 16);
        b[2] = (byte) ((i & 0x0000ff00) >> 8);
        b[3] = (byte) (i & 0x000000ff);
        return b;
    }

    // 从byte数组的index处的连续4个字节获得一个int
    public static int getInt(byte[] arr, int index) {
        return (0xff000000 & (arr[index + 0] << 24)) |
                (0x00ff0000 & (arr[index + 1] << 16)) |
                (0x0000ff00 & (arr[index + 2] << 8)) |
                (0x000000ff & arr[index + 3]);
    }

    // https://www.iteye.com/blog/tjmljw-1767716  小端序
    public static byte[] getBytesOrderSmall(int data) {
        byte[] bytes = new byte[4];
        bytes[0] = (byte) (data & 0xff);
        bytes[1] = (byte) ((data & 0xff00) >> 8);
        bytes[2] = (byte) ((data & 0xff0000) >> 16);
        bytes[3] = (byte) ((data & 0xff000000) >> 24);
        return bytes;
    }

    public static int getIntOrderSmall(byte[] bytes, int index, int byteLen) {
        int byte1 = (0xff & bytes[index]);
        if (byteLen == 1) {
            return byte1;
        }
        int byte2 = byte1
                | (0xff00 & (bytes[index + 1] << 8));
        if (byteLen == 2) {
            return byte2;
        }
        int byte3 = byte2
                | (0xff0000 & (bytes[index + 2] << 16));
        if (byteLen == 3) {
            return byte3;
        }
        int byte4 = byte3
                | (0xff000000 & (bytes[index + 3] << 24));
        return byte4;
//        return (0xff & bytes[index])
//                | (0xff00 & (bytes[index+1] << 8))
//                | (0xff0000 & (bytes[index+2] << 16))
//                | (0xff000000 & (bytes[index+3] << 24));
    }


    public static int[] toPixelInts(byte[] bytes, int byteLen) {
        int[] rs = new int[bytes.length / byteLen];
        for (int i = 0, j = 0; i < bytes.length; i += byteLen, j++) {
//            byte[] temp = new byte[4];
//            System.arraycopy(bytes, i, temp, 0, 4);
//            rs[j] = toRGBInt(temp);

            rs[j] = getIntOrderSmall(bytes, i, byteLen);
//            rs[j] = getInt(bytes, i);
        }
        return rs;
    }

    public static void main(String[] args) throws IOException {

//        DataOutputStream outputStream = new DataOutputStream(new FileOutputStream("D:\\project\\spot\\test-纯数据二进制"));
//        outputStream.writeUTF("使用writeUTF()方法写入数据"); // 将字符串写入文件
//        int sizes = 721*362;
//        for (int i = 0; i < sizes; i++) {
//            outputStream.write(99999);
//        }
//        outputStream.writeDouble(19.8);// 将double数据写入文件
//        outputStream.writeInt(298);// 将int数据写入文件
//        outputStream.writeBoolean(true);// 将boolean数据写入文件
//        outputStream.close(); // 关闭写入流

        recoverImageData("D:\\project\\spot\\wind-surface (1).jpg");

        /*GribJson gribJson = resolveGribJson("D:\\project\\spot\\20071612(1).json");
        float[] data = gribJson.getData();
        int[] intData = new int[data.length];
        for (int i = 0; i < data.length; i++) {
            intData[i] = (int) (data[i] * 100000);
        }
        int width = gribJson.getWidth();
        int height = gribJson.getHeight();

        String path1 = "D:\\project\\spot\\方式1-纯数据二进制.png";
        createImage1(path1, width, height, intData);
        recoverImageData(path1);*/

//        String path2 = "D:\\project\\spot\\方式2-纯数据二进制.png";
//        createImage2(path2, width, height, intData);
//        recoverImageData(path2);

//        recoverImageData("D:\\\\project\\\\spot\\\\20071707.png");
    }

    /**
     * 获取纯数据组
     *
     * @return
     * @throws IOException
     */
    public static GribJson resolveGribJson(String path) throws IOException {
        String s = FileUtils.readFileToString(new File(path));
        ObjectMapper objectMapper = new ObjectMapper();
        GribJson gribJson = objectMapper.readValue(s, GribJson[].class)[0];

        int width = gribJson.getWidth();
        int height = gribJson.getHeight();
        float[] data = gribJson.getData();
        StringBuilder builder = new StringBuilder();
        int a = 0;
        for (float d : data) {
            a++;
            builder.append(d).append(",");
            if (a % width == 0) {
                builder.append("\n");
            }
        }
        FileUtils.writeStringToFile(new File(path + "原纯数据组"), builder.toString());

        return gribJson;
    }

    /**
     * 还原纯数据二进制
     *
     * @throws FileNotFoundException
     */
    public static void recoverImageData(String path) throws IOException {
        long l = System.currentTimeMillis();
        BufferedImage image = ImageIO.read(new FileInputStream(path));
        // 获取位深
        int pixelSize = image.getColorModel().getPixelSize();
        int width = image.getWidth();
        int height = image.getHeight();
        DataBuffer dataBuffer = image.getRaster().getDataBuffer();
        DataBufferByte dataBufferByte = (DataBufferByte) dataBuffer;
        byte[] pixels = dataBufferByte.getData();
        int[] ints = toPixelInts(pixels, pixelSize / 8);

        StringBuilder builder = new StringBuilder();
        int b = 0;
        for (int i = 0; i < ints.length; i++) {
            b++;
            builder.append(ints[i]).append(",");
            if (b % width == 0) {
                builder.append("\n");
            }
//            if (i != ints[i]) {
//                throw new RuntimeException("解析出来的数据与源数据不一致");
//            }
        }
        FileUtils.writeStringToFile(new File(path + "-还原"), builder.toString());
        long l1 = System.currentTimeMillis();
        System.out.println(String.format("解析%s耗时：%s ms", path, (l1 - l)));
    }

    public static void createImage1(String path, int width, int height, int[] pixelData) throws IOException {
        long l = System.currentTimeMillis();
        // 设定 BufferedImage 的宽与高
        int size = width * height;
        //像素点
        int[] pixels = new int[size];

        for (int i = 0; i < pixels.length; i++) {
            pixels[i] = pixelData[i];
        }

        // 创建数组，用以保存对应 BufferedImage 的像素集合
        DataBuffer dataBuffer = new DataBufferInt(pixels, size);

        // 创建一个 WritableRaster 对象，用以 管理光栅
        WritableRaster raster = Raster.createPackedRaster(dataBuffer, width, height, width, new int[]{0xFF000000, 0xFF0000, 0xFF00, 0xFF}, null);
        // 创建一个 32 位的 ARGB 色彩模型，并填充相应的 A、R 、 G 、 B 掩码
        DirectColorModel directColorModel = new DirectColorModel(32, 0xFF000000, 0xFF0000, 0xFF00, 0xFF);

//        // 创建一个 WritableRaster 对象，用以 管理光栅
//        WritableRaster raster = Raster.createPackedRaster(dataBuffer, width, height, width, new int[]{0xFF0000, 0xFF00, 0xFF}, null);
//        // 创建一个 24 位的 ARGB 色彩模型，并填充相应的 R 、 G 、 B 掩码
//        DirectColorModel directColorModel = new DirectColorModel(24, 0xFF0000, 0xFF00, 0xFF);

        // 生成 BufferedImage, 预设 Alpha ，无配置
        BufferedImage image = new BufferedImage(directColorModel, raster, false, null);

//        Raster data = image.getData();
//        WritableRaster raster1 = image.getRaster();

        //压缩
        //image.getGraphics().drawImage(image.getScaledInstance(width,height,Image.SCALE_SMOOTH), 0, 0, null);
        ImageIO.write(image, "png", new File(path));
        long l1 = System.currentTimeMillis();
        System.out.println(String.format("生成%s耗时：%s ms", path, (l1 - l)));

    }

    public static void createImage2(String path, int width, int height, int[] pixelData) throws IOException {
        long l = System.currentTimeMillis();
        int size = width * height;
        int[] pixels = new int[size];
        for (int i = 0; i < pixels.length; i++) {
            //对于风速 采用 16位标识  int 前 16位 有符号U向风，后16位有符号V向风  16位表示区间 -32768 到 32767
            //对于气压 温度 湿度 全部采用 24位
//            pixels[i] = ((int)(Math.random()* 32767)<< 16)+((int)(Math.random()* 32767));
            pixels[i] = pixelData[i];//((int)(Math.random()* 32767));
        }

        // 32 位色彩模型
        DirectColorModel directColorModel = new DirectColorModel(32, 0xFF000000, 0xFF0000, 0xFF00, 0xFF);
        //以 SinglePixelPackedSampleModel 构建像素包
        SampleModel sample = new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, width, height, new int[]{0xFF000000, 0xFF0000, 0xFF00, 0xFF});

//        // 24 位色彩模型
//        DirectColorModel directColorModel = new DirectColorModel(24, 0xFF0000, 0xFF00, 0xFF);
//        //以 SinglePixelPackedSampleModel 构建像素包
//        SampleModel sample = new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, width, height, new int[]{0xFF0000, 0xFF00, 0xFF});

        DataBuffer dataBuffer = new DataBufferInt(pixels, size);
        // 以 SampleModel 及 DataBuffer 生成 WritableRaster
        WritableRaster raster = Raster.createWritableRaster(sample, dataBuffer, new Point(0, 0));
        // 生成 BufferedImage
        BufferedImage image = new BufferedImage(directColorModel, raster, false, null);
        ImageIO.write(image, "png", new File(path));
        long l1 = System.currentTimeMillis();
        System.out.println(String.format("生成%s耗时：%s ms", path, (l1 - l)));
    }

    public static class GribJson {
        private HashMap<String, Object> header;
        private float[] data;

        public HashMap<String, Object> getHeader() {
            return header;
        }

        public void setHeader(HashMap<String, Object> header) {
            this.header = header;
        }

        public float[] getData() {
            return data;
        }

        public void setData(float[] data) {
            this.data = data;
        }

        public int getWidth() {
            return (int) header.get("nx");
        }

        public int getHeight() {
            return (int) header.get("ny");
        }
    }
}
